<?php
/**
 * Created by PhpStorm.
 * User: lizx
 * Date: 2018/1/30
 * Time: 10:11
 */

namespace app\common\Server;

use app\common\Service;
use think\Config;

class Captcha extends Service
{

    private $redis = null;
    private $config = null;

    //有效时间（10分钟）
    const EXPIRE = 600;

    //键名
    const PREFIX = 'CACHE:CAPTCAH:%s';

    //发送时间隔限制
    const INTERVAL = 'CACHE:CAPTCAH:LOCKED:%s';

    //当天发送次数
    const COUNTS   = 'CACHE:CAPTCAH:COUNT:%s:%s';	// 手机号 - 日期

    public function __construct()
    {
        $redis = new Redis();
        $this->redis = $redis->handler();
        $this->config = Config::get('captcha');
//        $this->redis = Redis::getInstance();
    }

    /**
     * 发送验证码
     * @param $phone
     * @param int $sms_type
     * @return bool|int
     */
    public function send($phone, $sms_type = 0)
    {
        $res = $this->check($phone);
        if(!$res){
            return self::$data;
        }
        $code = $this->set($phone);
        $rtn = Sms::instance()->sendCaptch($phone, $code, $sms_type);

        if($rtn){
            return true;
        }
        self::$data['err'] = '999992';
        return false;
    }

    /**
     * 检查是否允许发送验证码
     * @param $phone
     * @return bool|int
     */
    public function check($phone)
    {
        $redis = $this->redis;
        //是否在重复发布限制内
        $mkey  = sprintf(self::INTERVAL, $phone);
        if ($redis->exists($mkey)){
            self::$data['err'] = '801002';
            return false;
        }

        //是否超出当日发送限制
        $nkey = sprintf(self::COUNTS, $phone, date('Ymd'));
        $numb = intval($redis->get($nkey));
        if ($numb > $this->config['daylimit']){
            self::$data['err'] = '801003';
            return false;
        }

        return true;
    }

    /**
     * 设置验证码
     * @param $phone
     * @return int
     */
    public function set($phone)
    {
        $redis = $this->redis;

        $ckey  = sprintf(self::PREFIX, $phone);

        //如果该验证码在有效期内，不更新验证码，不刷新有效时间
        if(!($code = $redis->get($ckey) ?? '')){
            $code  = rand(100000, 999999);
            $redis->setex($ckey, self::EXPIRE, $code);
        }

        //设置两次间隔
        $mkey  = sprintf(self::INTERVAL, $phone);
        $redis->setex($mkey, $this->config['interval'], time());

        //每天请求次数递增
        $nkey = sprintf(self::COUNTS, $phone, date('Ymd'));
        $redis->incr($nkey);
        $redis->expire($nkey, 86400);

        return $code;
    }
}